home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <string.h>
-
- /****************************************************/
- /* Descramble.c: */
- /* A procedure that returns a smooth transition */
- /* from one string to another with the same */
- /* characters, but in a different order. */
- /* Author: Jeremy Vineyard */
- /* */
- /* Includes: <stdLib.h>, <string.h> */
- /****************************************************/
-
- void Descramble(
- Str255 startString,
- Str255 endString,
- unsigned short numSteps,
- Str255 *stepStringPtrs[20] )
- {
- short i, j, k;
- short strLength = startString[0];
- div_t divResult;
- short destination, memSwitch;
- Boolean switchPossible;
-
- short distances[256];
- short destMap[256];
- Boolean destSwitchMap[256];
- Boolean checkList[256];
-
- /* Clear the destination switching map for use. */
- /* Only clear it up to strLength to save time. */
- for (i = 1; i <= strLength; i++)
- destSwitchMap[i] = false;
-
- /* This loop searches for a duplicate char 'j' for the char 'i'. */
- /* Once it finds a duplicate, it checks to see whether it is */
- /* already being used as another char's destination. If not, it */
- /* shows that char 'j' is char 'i's destination, sets the destMap */
- /* to show that char 'j' is being used, and calculates how far the */
- /* char 'i' needs to travel on each step to get to its destination.*/
- for (i = 1; i <= strLength; i++)
- for (j = 1; j <= strLength; j++)
- if ( startString[i] == endString[j] && ! destSwitchMap[j] )
- {
- /* If destSwitchMap[j] is set, then it already has */
- /* a char which is using it for a destination. */
- destSwitchMap[j] = true;
-
- /* Remember this char's destination. */
- destMap[i] = j;
-
- /* Find out how far this char should move on each step. */
- if (i == j)
- distances[i] = 0;
- else
- {
- divResult = div(j - i, numSteps);
- distances[i] = divResult.quot;
-
- /* Use the remainder to make sure this char moves each step. */
- if (divResult.rem != 0)
- if (divResult.rem < 0)
- distances[i] -= 1;
- else
- distances[i] += 1;
-
- /* Increment to exit this loop. */
- j = 512;
- }
- }
-
- /* In this loop, each character tries to move towards */
- /* its destination. Its distance is then recalculated */
- /* to compensate for it being switched. */
- /* This creates a 'morphing' effect, where the letters */
- /* in the start string gradually change into their */
- /* positions in the end string. */
- for (i = 0; i < numSteps; i++)
- {
- /* Copy the appropriate string for switching. */
- if (i > 0)
- memcpy(*stepStringPtrs[i], *stepStringPtrs[i - 1], strLength + 1);
- else
- memcpy(*stepStringPtrs[0], startString, strLength + 1);
-
- /* Clear the check list for use. */
- for (k = 1; k <= strLength; k++)
- checkList[k] = false;
-
- /* This loop switches characters until switchPossible = false. */
- do
- {
- switchPossible = false;
-
- for (j = 1; j <= strLength; j++)
- {
- if (distances[j] != 0 && ! checkList[j])
- {
- /* Calculate this char's intended destination for this step. */
- destination = j + distances[j];
-
- if (checkList[destination])
- {
- /* If the destination has already been used, */
- /* find the nearest one to it to switch to. */
- destination = -1;
-
- if (distances[j] > 0)
- for (k = destination - 1; k > j; k -= 1)
- if (! checkList[k] && distances[k] != 0)
- {
- destination = k;
- k = 512;
- }
- else;
- else
- for (k = destination + 1; k < j; k++)
- if (! checkList[k] && distances[k] != 0)
- {
- destination = k;
- k = 512;
- }
- }
-
- if (destination > 0)
- {
- /* If destination is a valid number, */
- /* Do the neccessary switching. */
-
- /* Switch the characters in the string */
- memSwitch = stepStringPtrs[i][0][destination];
- stepStringPtrs[i][0][destination] = stepStringPtrs[i][0][j];
- stepStringPtrs[i][0][j] = memSwitch;
-
- /* Switch the character's mapped destinations. */
- memSwitch = destMap[destination];
- destMap[destination] = destMap[j];
- destMap[j] = memSwitch;
-
- /* Show that the destination has been switched. */
- checkList[destination] = true;
-
- /* Recalculate the switched char's distance. */
- if (destMap[j] == j)
- distances[j] = 0;
- else if (i + 1 < numSteps)
- {
- divResult = div(destMap[j] - j, numSteps - i - 1);
- distances[j] = divResult.quot;
- if (divResult.rem != 0)
- if (divResult.rem < 0)
- distances[j] -= 1;
- else
- distances[j] += 1;
- }
-
- switchPossible = true;
- }
- }
- }
- } while (switchPossible);
-
- if (i + 1 == numSteps)
- return;
-
- /* Recalculate all distances to compensate for switched char's. */
- for (k = 1; k <= strLength; k++)
- if (distances[k] != 0)
- {
- if (destMap[k] == k)
- distances[k] = 0;
- else if (i + 1 < numSteps)
- {
- /* Recalculate how far this char needs to move */
- /* with the number of steps that are left. */
- divResult = div(destMap[k] - k, numSteps - i - 1);
- distances[k] = divResult.quot;
- if (divResult.rem != 0)
- if (divResult.rem < 0)
- distances[k] -= 1;
- else
- distances[k] += 1;
- }
- }
- }
- }
-
- main()
- {
- short i;
- Str255 *stepStrings[20];
-
- /* VERY IMPORTANT: */
- /* If stepStrings[x] are not allocated with */
- /* a call to malloc, then they will have */
- /* null values!! */
- for (i = 0; i < 20; i++)
- stepStrings[i] = malloc(256);
-
- Descramble("\pFORT RED BORDER", "\pROBERT REDFORD", 4, stepStrings);
- }
-